package com.jl15988.mybatispluskit.join.utils;

import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * Lambda 表达式工具类
 * 用于解析 Lambda 表达式，获取字段名等信息
 * 
 * @author Jalon
 * @since 2025/1/1
 */
public class LambdaUtils {
    
    /**
     * 从 Lambda 表达式中获取字段名
     * 
     * @param function Lambda 表达式
     * @param <T> 实体类型
     * @return 字段名
     */
    public static <T> String getFieldName(SFunction<T, ?> function) {
        try {
            // 获取 Lambda 表达式的序列化信息
            SerializedLambda serializedLambda = getSerializedLambda(function);
            
            // 从方法名中提取字段名
            String methodName = serializedLambda.getImplMethodName();
            
            // 处理 getter 方法名，提取字段名
            if (methodName.startsWith("get")) {
                String fieldName = methodName.substring(3);
                return firstToLowerCase(fieldName);
            } else if (methodName.startsWith("is")) {
                String fieldName = methodName.substring(2);
                return firstToLowerCase(fieldName);
            }
            
            // 如果不是标准的 getter 方法，直接返回方法名
            return methodName;
        } catch (Exception e) {
            throw new RuntimeException("无法解析 Lambda 表达式: " + function, e);
        }
    }
    
    /**
     * 获取 Lambda 表达式的序列化信息
     * 
     * @param function Lambda 表达式
     * @return 序列化信息
     * @throws Exception 异常
     */
    private static SerializedLambda getSerializedLambda(Serializable function) throws Exception {
        Method writeReplace = function.getClass().getDeclaredMethod("writeReplace");
        writeReplace.setAccessible(true);
        return (SerializedLambda) writeReplace.invoke(function);
    }
    
    /**
     * 首字母转小写
     * 
     * @param str 字符串
     * @return 首字母小写的字符串
     */
    private static String firstToLowerCase(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        return Character.toLowerCase(str.charAt(0)) + str.substring(1);
    }
    
    /**
     * 从 Lambda 表达式中获取数据库字段名（下划线命名）
     * 
     * @param function Lambda 表达式
     * @param <T> 实体类型
     * @return 数据库字段名
     */
    public static <T> String getColumnName(SFunction<T, ?> function) {
        String fieldName = getFieldName(function);
        return TableInfoUtils.camelToUnderline(fieldName);
    }
    
    /**
     * 从 Lambda 表达式中获取实体类类型
     * 
     * @param function Lambda 表达式
     * @param <T> 实体类型
     * @return 实体类类型
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getEntityClass(SFunction<T, ?> function) {
        try {
            // 获取 Lambda 表达式的序列化信息
            SerializedLambda serializedLambda = getSerializedLambda(function);
            
            // 获取实现类的类名
            String implClass = serializedLambda.getImplClass();
            
            // 将类名转换为 Class 对象
            String className = implClass.replace('/', '.');
            return (Class<T>) Class.forName(className);
        } catch (Exception e) {
            throw new RuntimeException("无法从 Lambda 表达式中获取实体类类型: " + function, e);
        }
    }
} 